#ifndef MAIN_H
#define MAIN_H
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <functional>
#include <sstream>
#include <math.h>
#include <map>
#include <iomanip>
#include <time.h>
#include <stdlib.h>
#include <cmath>
#include <limits.h>
#include <malloc.h>
#include <memory.h>
#include <numeric>
#include <ctime>    // For time()
#include <cstdlib>  // For srand() and rand()
using namespace std;
const static char ENTER = 10;
//***************************************************
const static int numberOfAtt = 55;
//const static int numberOfAtt = 6;


//***************************************************
const int MINUTES_IN_HOUR = 60;
const int SECONDS_IN_MINUTE = 60;

bool static kmeans = false;
bool static kmeanpp = true;
//==============================================================================

inline void menuBuildUp(char* &inputFile, char* &outputFile) {
	string selectedNo = "";
	// How to get a number.
	int myNumber = 0;
	while (true) {
		cout << "Choose input files [1-3]: " << endl;
		cout << "**********************************************" << endl;
		cout << "1. [raw]dataselect-2008.txt" << endl;
		cout << "2. test.txt" << endl;
		cout << "3. test2.txt" << endl;
		cout << "**********************************************" << endl;
		cout << "Select number : ";
		getline(cin, selectedNo);
		// This code converts from string to number safely.
		stringstream myStream(selectedNo);
		if (myStream >> myNumber)
			break;
		cout << "Invalid number, please try again" << endl;
	}
	cout << "You entered: " << selectedNo << endl << endl;

	if (myNumber == 1) {
		inputFile = "INPUT-USED/[raw]dataselect-2008.txt";
		outputFile = "INPUT-USED/ANSWER/[dp-op]dataselect-2008.txt";
	
	} else if (myNumber == 2) {
		inputFile = "INPUT-USED/test.txt";
		outputFile = "INPUT-USED/ANSWER/[dp-op]test.txt";

	} else if (myNumber == 3) {
		inputFile = "INPUT-USED/test2.txt";
		outputFile = "INPUT-USED/ANSWER/[dp-op]test2.txt";
	
	}

	else {
		inputFile = "";
		outputFile = "";
		cout << "File not found\n" << endl;
		//exit(0);
	}

}

//==============================================================================
// Function for wait the key. Press 'ENTER' to exit
inline void waitEndKey() {
	auto char c = 0;
	while (c != ENTER) {
		printf("\nWait for exit. Please press ENTER Key....\n");
		c = getchar();
		//printf("key %d press\n",c);
	}
	if (c == ENTER) {
		printf("See you....");
		exit(0);
	}
}
//==============================================================================


/*+++++++++++++++++++++++++++++++++++++[Global class]+++++++++++++++++++++++++++++++++++*/
//change each element of the string to lower case
inline string StringToLower(string strToConvert) {
	for (unsigned int i = 0; i < strToConvert.length(); i++) {
		strToConvert[i] = tolower(strToConvert[i]);
	}
	return strToConvert;//return the converted string
}
//=============================================================================
//change case of all string into lower case
inline vector<string> toLowerCase(vector<string> sortEle) {
	int sortSize = sortEle.size();
	for (int i = 0; i < sortSize; i++) {
		transform(sortEle[i].begin(), sortEle[i].end(), sortEle[i].begin(),
				ptr_fun<int, int> (&tolower));
	}
	return sortEle;//return the lower case string
}
//=============================================================================
//split a string with separator sign into 3 sub strings
inline void split3string(string str, char separator, string &first,
		string &second, string &third) {

	istringstream text(str);
	getline(text, first, separator);
	getline(text, second, separator);
	getline(text, third, separator);
}
//=============================================================================
//split a string with separator sign into 2 sub strings
inline void splitstring(string str, char separator, string &first1,
		string &second1) {
	istringstream text(str);
	getline(text, first1, separator);
	getline(text, second1, separator);
}
//=============================================================================
//convert to double
inline double to_double(const char *p) {
	std::stringstream ss(p);
	double result = 0;
	ss >> result;
	return result;
}
//=============================================================================
//convert to string
inline string to_string(double num) {
	stringstream s_num;
	string s_str;
	s_num.str("");
	s_num << num;
	s_str = s_num.str();
	return s_str;
}
inline int GetSecond() {
	//cout<<clock()<<" / "<<CLOCKS_PER_SEC<<endl;
	return int(clock()) % CLOCKS_PER_SEC;
}
//=============================================================================
inline int GetRandom(int n) {
	srand((unsigned int) time(0));
	int Max = n;
	int a = rand();
	int c = rand();
	//cout<<"A : "<<a<<" C: "<<c<<endl;
	//cout<<"GetSecond : "<<GetSecond()<<endl;
	int u = rand() * RAND_MAX + rand();
	//int u = (a * GetSecond() + c) % Max;
	//cout<<"GetRandom : "<<u<<endl;
	return ((u % Max) + Max) % Max;

}
//=============================================================================
inline void LOG(const string msg) {
	if (msg.size() > 0) {
		cout << msg << endl;
		return;
	}
}
//=============================================================================
inline string counterTime(int diff) {

	string setTime = "";
	int Hours = 0;
	int Minutes = 0;
	int Seconds = 0;
	int InMinutes = 0;
	int InSeconds = 0;
	int MilliSeconds = 0;
//diff = 677953;
	MilliSeconds = diff % 1000;
	InSeconds = diff / 1000;

	Seconds = InSeconds % SECONDS_IN_MINUTE;
	InMinutes = InSeconds / SECONDS_IN_MINUTE;

	Minutes = InMinutes % MINUTES_IN_HOUR;
	Hours = InMinutes / MINUTES_IN_HOUR;

	if (Hours == 0)
		setTime.append("00");
	else
		setTime.append(to_string(Hours));

	setTime.append(" Hrs. : ");

	if (Minutes == 0)
		setTime.append("00");
	else
		setTime.append(to_string(Minutes));

	setTime.append(" Mins. : ");

	if (Seconds == 0)
		setTime.append("00");
	else
		setTime.append(to_string(Seconds));

	setTime.append(" Secs. : ");

	if (MilliSeconds == 0)
		setTime.append("00");
	else
		setTime.append(to_string(MilliSeconds));

	setTime.append(" mSecs");
	//cout<<setTime<<endl;
	if (setTime != "")
		return setTime;
	else
		return "unknown";

	
}
//=============================================================================

//inline void writeLogIO(string diff_dp_str, string diff_km_str,
//		string diff_kmpp_str, string diff_od_str, string diff_tt_str, int base,
//		string baseName, int k, vector<int> outlier_pointID,
//		vector<string> outlier_centerID, vector<double> lof_p,
//		vector<string> local_outlier_status,
//		vector<string> sortCID_return_kmpp, vector<int> sortPID_return_kmpp) {
//
//	int outlier_pointIDSize = outlier_pointID.size();
//	char sdate[9];
//	char stime[9];
//	_strdate(sdate);
//	_strtime(stime);
//
//	string outfile = "";
//
//	//outfile.append("INPUT-USED/ANSWER/[");
//	//outfile.append((string)sdate);
//	//outfile.append("LOG_");
//	//outfile.append((string)stime);
//	//outfile.append(".txt");
//	//cout<< outfile <<endl;
//	//ofstream out(outfile.c_str());
//	ofstream out("INPUT-USED/ANSWER/LOG.txt");
//
//	if (!out) {
//		cout << "Cannot open file.\n";
//	} else {
//		//---------------------------------------------------------------------------------------
//		out << "Record at " << (string) sdate << " Time at " << (string) stime
//				<< endl;
//		out
//				<< "====================[ Summary : Data preprocessing ]===================="
//				<< endl;
//		out << "[ Time spending... ] " << endl;
//		out << "\tPhase 1 -> Data preprocessing [HH:MM:SS:MS] : "
//				<< diff_dp_str << endl;
//		out << "[ Processing... ] " << endl;
//		out << "\tBase attribute at : " << base << " < " << baseName << " > "
//				<< endl;
//		out
//				<< "============================================================================================================================\r\n\r\n"
//				<< endl;
//
//		//---------------------------------------------------------------------------------------
//		out
//				<< "====================[ Summary : K-means++ ]===================="
//				<< endl;
//		out << "[ Time spending... ] " << endl;
//
//		if (diff_km_str != "")
//			out << "\tPhase 2 -> K-means [HH:MM:SS:MS] : " << diff_km_str
//					<< endl;
//
//		if (diff_kmpp_str != "")
//			out << "\tPhase 2 -> K-means++ [HH:MM:SS:MS] : " << diff_kmpp_str
//					<< endl;
//
//		out << "[ Processing... ] " << endl;
//		out << "\tThe number of K : " << k << endl;
//	
//		for (int i = 0; i < sortCID_return_kmpp.size(); i++) {
//			out << "\t\t => " << sortCID_return_kmpp[i] << " with point id : "
//					<< sortPID_return_kmpp[i] << endl;
//		}
//		out
//				<< "============================================================================================================================\r\n\r\n"
//				<< endl;
//
//		//---------------------------------------------------------------------------------------
//		out
//				<< "====================[ Summary : Outlier detection ]===================="
//				<< endl;
//		out << "[ Time spending... ] " << endl;
//		out << "\tPhase 3 -> Outlier detection [HH:MM:SS:MS] : " << diff_od_str
//				<< endl;
//		out << "[ Processing... ] " << endl;
//
//		out << "Point ID with outliers: " << endl;
//		//cout<<lof_p.size()<< " == " << local_outlier_status.size() << " == " <<outlier_pointIDSize<<endl;
//		for (int i = 0; i < outlier_pointIDSize; i++) {
//			out << "\t >> Point ID : " << outlier_pointID[i] << endl;
//			out << "\t\t - At center ID : " << outlier_centerID[i] << endl;
//			out << "\t\t - LOF(p) = " << lof_p[i] << endl;
//			if (local_outlier_status[i] == "o")
//				out << "\t\t - Status : Outlier" << endl;
//			else
//				out << "\t\t - Status : Inlier" << endl;
//		}
//
//		out
//				<< "============================================================================================================================\r\n\r\n"
//				<< endl;
//
//		//---------------------------------------------------------------------------------------
//		out << "====================[ All summary ]===================="
//				<< endl;
//		out << "Total -> [HH:MM:SS:MS] : " << diff_tt_str << endl;
//		out
//				<< "==================================================================================================================\r\n\r\n"
//				<< endl;
//	}
//	cout << "Write Log is done!" << endl;
//	out.close();
//
//}
//=============================================================================
inline void writeLogIODP(string diff_dp_str, int base,string baseName) {

	
	char sdate[9];
	char stime[9];
	_strdate(sdate);
	_strtime(stime);

	string outfile = "";

	
	ofstream out("INPUT-USED/ANSWER/[Phase1]LOG.txt");

	if (!out) {
		cout << "Cannot open file.\n";
	} else {
		//---------------------------------------------------------------------------------------
		out << "Record at " << (string) sdate << " Time at " << (string) stime
				<< endl;
		out
				<< "====================[ Summary : Data preprocessing ]===================="
				<< endl;
		out << "[ Time spending... ] " << endl;
		out << "\tPhase 1 -> Data preprocessing [HH:MM:SS:MS] : "
				<< diff_dp_str << endl;
		out << "[ Processing... ] " << endl;
		out << "\tBase attribute at : " << base << " < " << baseName << " > "
				<< endl;
		out
				<< "============================================================================================================================\r\n\r\n"
				<< endl;

		
	}
	cout << "Write Log is done!" << endl;
	out.close();

}
//=============================================================================
inline void writeLogIOOD(int MinPts,string diff_od_str, vector<int> outlier_pointID,vector<string> outlier_centerID, vector<double> lof_p,vector<string> local_outlier_status,
		vector<string> sortCID_return_kmpp, vector<int> sortPID_return_kmpp) {

	int outlier_pointIDSize = outlier_pointID.size();
	char sdate[9];
	char stime[9];
	_strdate(sdate);
	_strtime(stime);

	string outfile = "";

	
	ofstream out("INPUT-USED/ANSWER/[Phase3]LOG.txt");

	if (!out) {
		cout << "Cannot open file.\n";
	} else {
		//---------------------------------------------------------------------------------------
		out << "Record at " << (string) sdate << " Time at " << (string) stime
				<< endl;
		//---------------------------------------------------------------------------------------
		out
				<< "====================[ Summary : Outlier detection ]===================="
				<< endl;
		out << "[ Time spending... ] " << endl;
		out << "\tPhase 3 -> Outlier detection [HH:MM:SS:MS] : " << diff_od_str
				<< endl;
		out << "[ Processing... ] " << endl;
		out << "MinPts : " << MinPts << endl;
		out << "The number of outlier points : " << outlier_pointIDSize << endl;
		
		out << "Point ID with outliers: " << endl;
		//cout<<lof_p.size()<< " == " << local_outlier_status.size() << " == " <<outlier_pointIDSize<<endl;
		for (int i = 0; i < outlier_pointIDSize; i++) {
			out << "\t >> Point ID : " << outlier_pointID[i] << endl;
			out << "\t\t - At center ID : " << outlier_centerID[i] << endl;
			out << "\t\t - LOF(p) = " << lof_p[i] << endl;
			if (local_outlier_status[i] == "o")
				out << "\t\t - Status : Outlier" << endl;
			else
				out << "\t\t - Status : Inlier" << endl;
		}

		out	<< "===========================================================\r\n\r\n"<< endl;

	}
	cout << "Write Log is done!" << endl;
	out.close();

}
//=============================================================================
inline void writeLogIOKM(int count,vector<int> startCenter_km,vector<int> startCenter_kmpp,string diff_km_str,string diff_kmpp_str, int k, vector<string> sortCID_return_kmpp, vector<int> sortPID_return_kmpp, vector<string> sortCID_return_km, vector<int> sortPID_return_km) {

	
	char sdate[9];
	char stime[9];
	_strdate(sdate);
	_strtime(stime);

	string outfile = "";

	ofstream out("INPUT-USED/ANSWER/[Phase2]LOG.txt");

	if (!out) {
		cout << "Cannot open file.\n";
	} else {
		//---------------------------------------------------------------------------------------
		out << "Record at " << (string) sdate << " Time at " << (string) stime
				<< endl;
		
		//---------------------------------------------------------------------------------------
		out
				<< "====================[ Summary : K-means++ ]===================="
				<< endl;
		out << "[ Time spending... ] " << endl;

		if (diff_km_str != "")
			out << "\tPhase 2 -> K-means [HH:MM:SS:MS] : " << diff_km_str
					<< endl;

		if (diff_kmpp_str != "")
			out << "\tPhase 2 -> K-means++ [HH:MM:SS:MS] : " << diff_kmpp_str
					<< endl;

		out << "[ Processing... ] " << endl;
		out << "\tThe number of K : " << k << endl;
		out << "\tIteration : " << count << endl;
		if(startCenter_km.size()>0){
			for (int i = 0; i < startCenter_km.size(); i++) {
				out <<	"The start centers of K-means >> " << startCenter_km[i]<<endl;
			}
		}

		if(startCenter_kmpp.size()>0){
			for (int i = 0; i < startCenter_kmpp.size(); i++) {
				out <<	"The start centers of K-means >> " << startCenter_kmpp[i]<<endl;
			}
		}


		if(sortCID_return_kmpp.size() > 0 && sortPID_return_kmpp.size() > 0){
			for (int i = 0; i < sortCID_return_kmpp.size(); i++) {
				out << "\t\t => (" << sortCID_return_kmpp[i] << ", p_"
						<< sortPID_return_kmpp[i] <<" )" <<endl;
			}
		}

		if(sortCID_return_km.size() > 0 && sortPID_return_km.size()>0){
			for (int i = 0; i < sortCID_return_km.size(); i++) {
				out << "\t\t => (" << sortCID_return_km[i] << ", p_"
						<< sortPID_return_km[i] <<" )" <<endl;
			}
		}

		out
				<< "============================================================================================================================\r\n\r\n"
				<< endl;

		//---------------------------------------------------------------------------------------
		
	}
	cout << "Write Log is done!" << endl;
	out.close();
}
//=============================================================================

inline void writeLogIOSummary(string diff_tt_str) {


	char sdate[9];
	char stime[9];
	_strdate(sdate);
	_strtime(stime);

	string outfile = "";

	
	ofstream out("INPUT-USED/ANSWER/[Summary]LOG.txt");

	if (!out) {
		cout << "Cannot open file.\n";
	} else {
		//---------------------------------------------------------------------------------------
		out << "Record at " << (string) sdate << " Time at " << (string) stime
				<< endl;
	
		out << "====================[ All summary ]===================="
				<< endl;
		out << "Total -> [HH:MM:SS:MS] : " << diff_tt_str << endl;
		out
				<< "==================================================================================================================\r\n\r\n"
				<< endl;
	}
	cout << "Write Log is done!" << endl;
	out.close();

}
#endif
